package com.gitee.wsl.func.transform.sample

import com.gitee.wsl.base.Objects.equals
import com.gitee.wsl.func.transform.Transformer


/**
 * Transformer implementation that returns the same constant each time.
 *
 *
 * No check is made that the object is immutable. In general, only immutable
 * objects should use the constant factory. Mutable objects should
 * use the prototype factory.
 *
 *
 * @param <T> the type of the input to the function.
 * @param <R> the type of the result of the function.
 * @since 3.0
</R></T> */
class ConstantTransformer<T, R>(
    val constant: R?,
) : Transformer<T, R?>{
    /**
     * Gets the constant.
     *
     * @return the constant
     * @since 3.1
     */

    /**
     * {@inheritDoc}
     */
    override fun equals(obj: Any?): Boolean {
        if (obj === this) {
            return true
        }
        if (obj !is ConstantTransformer<*, *>) {
            return false
        }
        val otherConstant: Any? = obj.constant
        return equals<Any?>(otherConstant, this.constant)
    }

    /**
     * {@inheritDoc}
     */
    override fun hashCode(): Int {
        var result = "ConstantTransformer".hashCode() shl 2
        if (this.constant != null) {
            result = result or this.constant.hashCode()
        }
        return result
    }

    /**
     * Transforms the input by ignoring it and returning the stored constant instead.
     *
     * @param input  the input object which is ignored
     * @return the stored constant
     */
    override fun transform(input: T): R? {
        return this.constant
    }

    companion object {

        /** Returns null each time  */
        val NULL_INSTANCE = ConstantTransformer<Any,Any>(null)

        /**
         * Transformer method that performs validation.
         *
         * @param <I>  the input type
         * @param <O>  the output type
         * @param constantToReturn  the constant object to return each time in the factory
         * @return the `constant` factory.
        </O></I> */
        fun <I, O> constantTransformer(constantToReturn: O?): Transformer<I, O?> {
            if (constantToReturn == null) {
                return nullTransformer()
            }
            return ConstantTransformer(constantToReturn)
        }

        /**
         * Gets a typed null instance.
         *
         * @param <I>  the input type
         * @param <O>  the output type
         * @return Transformer&lt;I, O&gt; that always returns null.
        </O></I> */
        fun <I, O> nullTransformer(): Transformer<I, O> {
            return NULL_INSTANCE as Transformer<I, O>
        }
    }
}
